package com.stt.experiment.websocket.action.dispatcher;

import com.stt.experiment.websocket.action.dispatcher.annotation.*;
import com.stt.experiment.websocket.action.dispatcher.intercepter.ActionInterceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

@Component
@Order(0)  // @Order标记定义了组件的加载顺序，数字越小越早加载
public class ActionInitializer implements CommandLineRunner, ApplicationContextAware{
    private static final Logger log = LoggerFactory.getLogger(ActionInitializer.class);
    @Autowired
    private ActionDispatcher actionDispatcher;
    private ApplicationContext applicationContext;

    public ActionInitializer() {}

    @Override
    public void run(String... strings) throws Exception {
        this.initReqs();
        this.initInteceptors();
    }

    private void initReqs() {
        Map<ReqNames, ReqHandlers> actionMap = new HashMap<>();
        // 获取所有有@ReqAction注释的bean
        Map<String, Object> actions = this.applicationContext.getBeansWithAnnotation(ReqAction.class);
        Iterator var5 = actions.values().iterator();
        while(var5.hasNext()) {
            Object o = var5.next();
            Class<?> clazz = o.getClass();
            //获取类注解
            ReqAction reqAction = AnnotationUtils.findAnnotation(clazz, ReqAction.class);
            String module = reqAction.module();
            Method[] var9 = clazz.getMethods();
            int var10 = var9.length;

            for (int var11 = 0; var11 < var10; ++var11) {
                Method method = var9[var11];
                if (method.isAnnotationPresent(ReqMethod.class)) {
                    ReqMethod reqMethod = AnnotationUtils.findAnnotation(method, ReqMethod.class);
                    ReqNames reqNames = new ReqNames(module, reqMethod.cmd());
                    if (actionMap.containsKey(reqNames)) {
                        throw new RuntimeException("this ReqNames has already registered: " + reqNames.getModule() + ":" + reqNames.getCmd());
                    }
                    actionMap.put(reqNames, new ReqHandlers(o, method));
                    log.info("ReqMethod > [ {} / {} ] registered.", reqNames.getModule(), reqNames.getCmd());
                }
            }
        }
        this.actionDispatcher.setHandlerMap(actionMap);
    }

    private void initInteceptors() {
        Map<String, Object> interceptorMap = this.applicationContext.getBeansWithAnnotation(Interceptor.class);
        Iterator var2 = interceptorMap.values().iterator();

        while (var2.hasNext()) {
            Object inteceptor = var2.next();
            this.actionDispatcher.registerInterceptor((ActionInterceptor)inteceptor);
        }
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
